package ua.lviv.franko.solvers.stressanalysis.twoDimention.fem;

import java.util.ArrayList;
import java.util.List;

import ua.lviv.franko.integration.IFEMFunction2D;
import ua.lviv.franko.integration.IFunction2D;
import ua.lviv.franko.triangulation.SaveStructures.Node;

public class BiqubicrIsoparamerticQuadrilateral extends AbstractIsoparametricQuadrilateral {

	public BiqubicrIsoparamerticQuadrilateral(double k1, double k2, double k3, IFunction2D f1Function, IFunction2D f2Function, List<Node> nodes) {
		super(k1, k2, k3, f1Function, f2Function);

		this.nodes = nodes;
		this.pos = new ArrayList<Integer>();
		for (Node node : nodes) {
			pos.add(node.Number);
		}

		// add base functions

		// N1
		baseFunctions.add(generateFunction2dMainNodes(-1, -1));
		// N2
		baseFunctions.add(generateFunction2dHorizontalNodes(-1.0 / 3.0, -1));
		// N3
		baseFunctions.add(generateFunction2dHorizontalNodes(1.0 / 3.0, -1));
		// N4
		baseFunctions.add(generateFunction2dMainNodes(1, -1));
		// N5
		baseFunctions.add(generateFunction2dVerticalNodes(1, -1.0 / 3.0));
		// N6
		baseFunctions.add(generateFunction2dVerticalNodes(1, 1.0 / 3.0));
		// N7
		baseFunctions.add(generateFunction2dMainNodes(1, 1));
		// N8
		baseFunctions.add(generateFunction2dHorizontalNodes(1.0 / 3.0, 1));
		// N9
		baseFunctions.add(generateFunction2dHorizontalNodes(-1.0 / 3.0, 1));
		// N10
		baseFunctions.add(generateFunction2dMainNodes(1, -1));
		// N11
		baseFunctions.add(generateFunction2dVerticalNodes(-1, 1.0 / 3.0));
		// N12
		baseFunctions.add(generateFunction2dVerticalNodes(-1, -1.0 / 3.0));
	}

	public static IFEMFunction2D generateFunction2dHorizontalNodes(final double xi, final double yi) {
		return new IFEMFunction2D() {

			@Override
			public double calculate(double x, double y) {
				return 27.0 / 32.0 * (1 - x * x) * (1 + yi * y) * (1.0 / 3.0 + 3.0 * xi * x);
			}

			@Override
			public double calculateDerivatyX(double x, double y) {
				return 27.0 / 32.0 * ((2.0 * x) * (1 + yi * y) * (1.0 / 3.0 + 3.0 * xi * x) + (1 - x * x) * (1 + yi * y) * (3.0 * xi));
			}

			@Override
			public double calculateDerivatyY(double x, double y) {
				return 27.0 / 32.0 * ((1 - x * x) * (yi) * (1.0 / 3.0 + 3.0 * xi * x));
			}

			@Override
			public double getXi() {
				return xi;
			}

			@Override
			public double getYi() {
				return yi;
			}

			@Override
			public Node getNode() {
				// TODO Auto-generated method stub
				return null;
			}
		};
	}

	public static IFEMFunction2D generateFunction2dMainNodes(final double xi, final double yi) {
		return new IFEMFunction2D() {

			@Override
			public double calculate(double x, double y) {
				return 9.0 / 32.0 * (1 + xi * x) * (1 + yi * y) * (x * x + y * y - 10.0 / 9.0);
			}

			@Override
			public double calculateDerivatyX(double x, double y) {
				return 9.0 / 32.0 * ((xi) * (1 + yi * y) * (x * x + y * y - 10.0 / 9.0) + (1 + xi * x) * (1 + yi * y) * (x * 2.0));
			}

			@Override
			public double calculateDerivatyY(double x, double y) {
				return 9.0 / 32.0 * ((1 + xi * x) * (yi) * (x * x + y * y - 10.0 / 9.0) + (1 + xi * x) * (1 + yi * y) * (2.0 * y));
			}

			@Override
			public double getXi() {
				return xi;
			}

			@Override
			public double getYi() {
				return yi;
			}

			@Override
			public Node getNode() {
				// TODO Auto-generated method stub
				return null;
			}
		};
	}

	public static IFEMFunction2D generateFunction2dVerticalNodes(final double xi, final double yi) {
		return new IFEMFunction2D() {

			@Override
			public double calculate(double x, double y) {
				return 27.0 / 32.0 * (1 + xi * x) * (1 + y * y) * (1.0 / 3.0 + 3.0 * yi * y);
			}

			@Override
			public double calculateDerivatyX(double x, double y) {
				return 27.0 / 32.0 * (xi) * (1 + y * y) * (1.0 / 3.0 + 3.0 * yi * y);
			}

			@Override
			public double calculateDerivatyY(double x, double y) {
				return 27.0 / 32.0 * ((1 + xi * x) * (2.0 * y) * (1.0 / 3.0 + 3.0 * yi * y) + (1 + xi * x) * (1 + y * y) * (3.0 * yi));
			}

			@Override
			public double getXi() {
				return xi;
			}

			@Override
			public double getYi() {
				return yi;
			}

			@Override
			public Node getNode() {
				// TODO Auto-generated method stub
				return null;
			}
		};
	}

	@Override
	public double calculateSigma11(double x, double y, double[] vals) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public double calculateSigma12(double x, double y, double[] vals) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public double calculateSigma22(double x, double y, double[] vals) {
		// TODO Auto-generated method stub
		return 0;
	}

}
